package com.qdxwx.data.service.order;


import com.qdxwx.common.exception.AccountException;
import com.qdxwx.common.json.AjaxResult;
import com.qdxwx.common.page.PageRequest;
import com.qdxwx.common.utils.DateUtils;
import com.qdxwx.common.utils.TKServlet;
import com.qdxwx.common.utils.TKConvert;
import com.qdxwx.common.utils.TKString;
import com.qdxwx.data.mapper.order.OrderMapper;
import com.qdxwx.data.service.account.UserAccountDetailService;
import com.qdxwx.data.service.account.UserAccountService;
import com.qdxwx.data.service.course.CourseService;
import com.qdxwx.data.service.member.MemberRecordService;
import com.qdxwx.data.service.member.MemberSaleService;
import com.qdxwx.data.service.user.UserBuyService;
import com.qdxwx.data.service.user.UserInviteService;
import com.qdxwx.data.service.user.UserLetterService;
import com.qdxwx.models.account.UserAccount;
import com.qdxwx.models.account.UserAccountDetail;
import com.qdxwx.models.course.Course;
import com.qdxwx.models.enums.*;
import com.qdxwx.models.member.MemberSale;
import com.qdxwx.models.order.Order;
import com.qdxwx.models.order.OrderDetail;
import com.qdxwx.models.order.OrderQuery;
import com.qdxwx.models.order.OrderVO;
import com.qdxwx.models.user.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * Qdx NetSchool Platform
 * @author qdxwx
 * @updateTime 2022/5/25
 * @description
 */
@Service
public class OrderServiceImpl implements OrderService {

    private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private CourseService courseService;
    @Autowired
    private UserBuyService userBuyService;
    @Autowired
    private UserLetterService userLetterService;
    @Autowired
    private MemberRecordService memberRecordService;
    @Autowired
    private MemberSaleService memberSaleService;
    @Autowired
    private UserAccountService userAccountService;
    @Autowired
    private UserInviteService userInviteService;
    @Autowired
    private UserAccountDetailService userAccountDetailService;

    /**
     * 生成订单号 当前用户id+毫秒数
     */
    @Override
    public String createOrderNo(Long userId) {
        return userId + "P" + DateUtils.toString("yyyyMMddHHmmssSSS");
    }

    @Override
    public int insert(Order order) {
        if (order.getCreateTime() == null) {
            order.setCreateTime(LocalDateTime.now());
        }
        return orderMapper.insertOrder(order);
    }

    @Override
    public int delete(int id) {
        if (id > 0) {
            return orderMapper.deleteOrderById(id);
        } else {
            return 0;
        }
    }

    @Override
    public int deleteByIds(String ids) {
        List<Integer> idList = TKConvert.toIntList(ids);
        int count = 0;
        for (Integer id : idList) {
            count += delete(id);
        }
        return count;
    }

    @Override
    public int updateState(Order order) {
        return orderMapper.updateOrderStatus(order);
    }

    @Override
    public int updateOrder(Order order) {
        return orderMapper.updateOrder(order);
    }

    @Override
    public Order get(int orderId) {
        if (orderId < 1) return null;
        return orderMapper.selectOrderById(orderId);
    }

    @Override
    public Order getByOrderNo(String orderNo) {
        if (TKString.isEmpty(orderNo)){
            return null;
        }
        return orderMapper.selectOrderByOrderNo(orderNo);
    }

    @Override
    public List<Order> getList(OrderQuery order, PageRequest page) {
        return orderMapper.selectOrderList(order, page);
    }

    @Override
    public int count(OrderQuery order) {
        return orderMapper.countOrder(order);
    }

    /**
     * 个人中心订单查询
     */
    @Override
    public List<OrderVO> getListForUc(OrderQuery query, PageRequest page) {
        return orderMapper.selectOrderListForUc(query, page);
    }

    /**
     * 已支付和为支付的订单数量
     */
    @Override
    public int countByState(String status) {
        OrderQuery orderQuery = new OrderQuery();
        orderQuery.setStatus(status);
        return orderMapper.countOrder(orderQuery);
    }

    /**
     * 订单回调,余额支付订单操作 事物开启
     */
    @Override
    public AjaxResult updateCompleteOrder(HttpServletRequest request, Map<String, Object> sourceMap) {
        String orderNo = (String) sourceMap.get("orderNo");//请求订单号，系统内的
        String outTradeNo = (String) sourceMap.get("outTradeNo");//提交到支付宝的请求号
        //total_fee 为分，需要转为元
        int total_fee = TKConvert.toInteger(sourceMap.get("total_fee"));//支付金额,外界充值的金额，可能为0
        //支付方式
        PayType payType = PayType.get((String) sourceMap.get("payType"));
        if (payType == null) {
            return AjaxResult.error("支付方式错误！");
        }
        //查询订单
        Order order = getByOrderNo(orderNo);
        if (order == null) {
            return AjaxResult.error("找不到对应订单");
        }
        if (OrderStatus.SUCCESS.toString().equals(order.getStatus())) {
            logger.info("已支付成功，不需要再进行操作！orderId:" + order.getOrderId());
            return AjaxResult.success();//已成功，直接返回
        }
        if (!OrderStatus.INIT.toString().equals(order.getStatus())) {
            logger.error("订单状态异常！orderId:" + order.getOrderId());
            return AjaxResult.error("订单状态异常");
        }
        //第三方商户订单号
        order.setOutTradeNo(outTradeNo);
        //支付方式
        order.setPayType(payType.toString());
        if (total_fee > 0 && OrderType.ACCOUNT.equals(order.getOrderType())) {
            // 每次充值都有out_trade_no，防止重复充值做查询判断
            // 查询账户历史是否用out_trade_no，如果有了。抛出异常
            UserAccountDetail accountHistory = userAccountDetailService.getByOrderId(order.getOrderId(), order.getUserId());
            if (accountHistory != null) {
                logger.error("此订单已存在资金操作记录！orderId:" + order.getOrderId());
                throw new AccountException("此订单已存在资金操作记录！");
            }
            UserAccount userAccount = userAccountService.getByUserId(order.getUserId());
            userAccountService.income(userAccount, total_fee, AccountType.VM, AccountHistoryType.CASHLOAD, order.getOrderId(), "支付充值", true, AccountBizType.CASH);//充值订单
        }
        order.setStatus(OrderStatus.SUCCESS.toString());
        order.setPayTime(LocalDateTime.now());
        try {
            // 更新订单的状态
            updateOrderStatusSuccess(order);

            if (!OrderType.MEMBER.equals(order.getOrderType())) {
                //分销消费返现
                userInviteService.orderCashback(request, order);
            }
            //发送站内信
            userLetterService.send(order.getUserId(), LetterTemplate.ORDER_SUCCESS, order.getOrderNo());
        } catch (Exception e) {
            logger.error("send message error:" + e.getMessage());
        }
        return AjaxResult.success();
    }

    /**
     * 更新订单状态为成功,网银的回调
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderStatusSuccess(Order order) throws Exception {
        // 更新订单表状态
        int cnt = orderMapper.updateOrderStatusSuccess(order);
        if (cnt < 1) {
            return;
        }

        // 更新流水的状态
        OrderDetail update = new OrderDetail();
        update.setPayTime(order.getPayTime());
        update.setAuthStatus(OrderStatus.SUCCESS.toString());
        update.setOrderNo(order.getOrderNo());
        orderDetailService.updateOrderDetailStatusSuccess(update);

        //如果是课程
        if (OrderType.COURSE.equals(order.getOrderType())) {
            // 遍历订单课程集合，获得课程编号集合字符串
            List<OrderDetail> orderDetails = orderDetailService.getListByOrderId(order.getOrderId());
            if (orderDetails != null) {
                for (OrderDetail detail : orderDetails) {
                    //根据ids修改所买课程的购买数量
                    userBuyService.create(detail);
                    courseService.updateBuy(detail.getCourseId());
                }
            }
        } else if (OrderType.MEMBER.equals(order.getOrderType())) {
            OrderDetail detail = orderDetailService.getByOrderId(order.getOrderId());
            if (detail == null) {
                logger.error("找不到对应的订单流水,orderId:" + order.getOrderId());
                throw new RuntimeException("找不到对应的订单流水!");
            }
            MemberSale memberSale = memberSaleService.get(detail.getCourseId());
            if (memberSale == null) {
                logger.error("找不到对应的会员产品,saleId:" + detail.getCourseId());
                throw new RuntimeException("找不到对应的订单流水!");
            }
            // 处理会员记录
            memberRecordService.addByOrderDetail(detail, memberSale);
        } else if (OrderType.DOCUMENT.equals(order.getOrderType())) {
            OrderDetail detail = orderDetailService.getByOrderId(order.getOrderId());
            userBuyService.create(detail);
        }
    }

    @Override
    public void addFreeCourse(User user, Course course) throws Exception {
        if (course == null) {
            throw new Exception("课程不存在");
        }
        boolean isExist = userBuyService.checkIsBuy(user.getUserId(), ModuleType.COURSE.ordinal(), course.getCourseId());
        // 已经添加过无需重复添加
        if (isExist) {
            throw new Exception("此课程用户已经报名了");
        }
        // 拼装订单数据
        Order order = new Order();
        order.setCompanyId(user.getCompanyId());
        // 下单时间
        LocalDateTime date = LocalDateTime.now();
        order.setCreateTime(date);// 下单时间
        order.setUserId(user.getUserId());
        order.setUserName(user.getDisplayName());
        order.setOrderNo(createOrderNo(user.getUserId()));// 交易请求号
        order.setStatus(OrderStatus.SUCCESS.toString());// 交易装态,成功状态的
        order.setPayType("FREE");// 支付类型 免费
        order.setReqChannel("WEB");//ServletUtils.getChannel()
        order.setReqIp(TKServlet.getIpAddr());
        order.setOrderType(OrderType.COURSE.toString());
        order.setOrderAmount(course.getPrice()); // 原始金额
        order.setCouponAmount(course.getPrice());// 优惠金额
        order.setPayAmount(0);// 实际支付金额
        order.setDescription("赠送课程");
        order.setPayTime(date);// 支付时间
        // 添加订单
        insert(order);

        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setCompanyId(order.getCompanyId());
        // 订单id
        orderDetail.setOrderId(order.getOrderId());
        orderDetail.setOrderNo(order.getOrderNo());
        orderDetail.setOrderType(OrderType.COURSE.toString());
        // 添加流水表
        orderDetail.setUserId(user.getUserId());
        orderDetail.setUserName(user.getDisplayName());
        // 课程id
        orderDetail.setCourseId(course.getCourseId());
        // 课程名
        orderDetail.setCourseName(course.getCourseName());
        // 课程原始价格
        orderDetail.setSourcePrice(course.getPrice());
        // 课程实际支付价格
        orderDetail.setPrice(0);
        orderDetail.setAuthDate(course.getExpireDate());
        orderDetail.setAuthStatus(OrderStatus.SUCCESS.toString());
        orderDetail.setUpdateTime(date);
        // 支付时间
        orderDetail.setPayTime(date);
        orderDetail.setDescription("");
        // 下单时间
        orderDetail.setCreateTime(date);
        orderDetailService.insert(orderDetail);
        //将课程添加到用户课程里
        userBuyService.create(orderDetail);
    }

    @Override
    public void addFreeMember(User user, MemberSale memberSale) {
        // 拼装订单数据
        Order order = new Order();
        // 下单时间
        LocalDateTime date = LocalDateTime.now();
        order.setCreateTime(date);// 下单时间
        order.setUserId(user.getUserId());
        order.setUserName(user.getDisplayName());
        order.setOrderNo(this.createOrderNo(user.getUserId()));// 交易请求号
        order.setStatus(OrderStatus.SUCCESS.toString());// 交易装态,成功状态的
        order.setPayType(PayType.FREE.toString());// 支付类型 免费
        order.setReqChannel(ReqChannel.WEB.toString());
        order.setReqIp("");
        order.setOrderType(OrderType.MEMBER.toString());
        order.setOrderAmount(memberSale.getPrice()); // 原始金额
        order.setCouponAmount(memberSale.getPrice());// 优惠金额
        order.setPayAmount(0);// 实际支付金额
        order.setDescription("后台免费赠送会员");
        order.setPayTime(date);// 支付时间
        // 添加订单
        insert(order);

        // 创建流水
        OrderDetail detail = new OrderDetail();
        // 用户id
        detail.setUserId(user.getUserId());
        detail.setUserName(user.getDisplayName());
        // 商品id
        detail.setCourseId(memberSale.getId());
        // 订单id
        detail.setOrderId(order.getOrderId());

        /*到期时间*/
        detail.setAuthDate(LocalDate.now().plusDays(memberSale.getDays()));
        // 下单时间
        detail.setCreateTime(date);
        // 会员原始价格
        detail.setSourcePrice(memberSale.getPrice());
        // 会员实际支付价格
        detail.setPrice(0);
        // 会员名
        detail.setCourseName(memberSale.getName());
        // 会员状态（未开始）
        detail.setAuthStatus(OrderStatus.SUCCESS.toString());
        // 订单请求号
        detail.setOrderNo(order.getOrderNo());
        detail.setUpdateTime(date);
        // 支付时间
        detail.setPayTime(date);
        detail.setOrderType(OrderType.MEMBER.toString());
        detail.setDescription(memberSale.getName());
        orderDetailService.insert(detail);
        // 处理会员记录
        memberRecordService.addByOrderDetail(detail, memberSale);
    }

    @Override
    public long sumPayAmount(OrderQuery order) {
        Long sum = orderMapper.sumPayAmount(order);
        if (sum == null) {
            sum = 0L;
        }
        return sum;
    }

    @Override
    public List<Order> getListByTeacher(OrderQuery order, PageRequest page) {
        return orderMapper.selectListByTeacher(order,page);
    }

    @Override
    public long countByTeacher(OrderQuery order) {
        return orderMapper.countByTeacher(order);
    }

    @Override
    public Order getRepeatOrder(long userId, int otherId, String orderType) {
        if(userId < 1) return null;
        if(otherId < 1) return null;
        if(TKString.isEmpty(orderType)) return null;
        return orderMapper.selectRepeatOrder(userId,otherId,orderType);
    }

    @Override
    public int updateCombine(long userId1, long userId2) {
        if(userId1 < 1 || userId2 < 1){
            throw new RuntimeException("更新订单：参数错误");
        }
        return orderMapper.updateCombine(userId1,userId2);
    }
}